# encoding:utf-8
'''
@author : xaing
@time : 2018/4/6 11:18
@地址 : 广州
@作用 : 完整可以用的下载漫画的代码 ，此份为准
@结果 :
'''

import urllib.request
import re
import os
import time
import execjs
import socket


# 首页的url
baseUrl = 'http://www.hhcool.com/manhua/33213.html'
# 主要的url
mainUrl = 'http://www.hhcool.com'
# 图片的基url
baseImg = 'http://165.94201314.net/dm01/'
# 图片下载的基础位置
baseImgFile = "E:\\下载\\img18\\"
# 文件夹中图片的名字
imgInt = 0
# 初始化分文件夹的名字
# initImgFile = 1
initImgFile = 1


def mainDef():
    # 基页面
    baseHtml = getHtml(baseUrl)
    # 全部子页面
    allSon = getBaseUrl(baseHtml)
    # 反转列表
    allSonFan = allSon[::-1]
    # 可以指定索引位置，其中i是所有位置
    # for i, son in allSonFan:
    '''
    如果中间数据中断，那么可以用这种方式，指定前面的都直接跳过，不需要去继续执行(注意，设置图片文件名字initImgFile)，如果漫画是11集，那么这里为10，漫画文件那设置11
    '''
    for i, son in enumerate(allSonFan):
        if i < 0: #这里要笔initImgFile少1
            continue

        time.sleep(4)
        # 分页面的地址
        mUrl = mainUrl + son
        sonHtml = isStrHTML(mUrl)
        # 结束页面
        endPage = getEndPage(sonHtml)
        print("=============本话结束页面" + str(endPage) + "页")
        # 第一页的位置，根据页码慢慢叠加
        initInt = 1
        global initImgFile
        imgFile = baseImgFile + str(initImgFile) + "\\"
        # endPage是结束页面，initInt是1的14的时候还有15没爬，当是15的是等式已经不成立，则要 + 1，而下面又有一个+1，因为逻辑上是从0开始的
        while initInt < (int(endPage) + 2):
            # 获取当前子页面html
            presentHtml = nextUrl(sonHtml, initInt)
            # time.sleep(2)
            # 获取图片name
            imgName = getImg(getHtml(presentHtml))
            # 获取到图片的地址
            imgUrl = decryptionImg(imgName)
            global imgInt
            downImg(imgFile, imgUrl, imgInt)
            imgInt = imgInt + 1

            if initInt == int(endPage):
                print("=================终止本话的爬取。。。。已经爬到" + str(initInt) + "页")
                imgInt = 0
                initImgFile = initImgFile + 1
                break
            else:
                # 获取下一个页面
                nextPage = nextUrl(sonHtml, initInt + 1)
                sonHtml = getHtml(nextPage)
                print("=================爬取子页面第" + str(initInt) + "页")
                initInt = initInt + 1


def downImg(imgFile, urlImg, imgName):
    '''
    下载图片
    :param urlImg: 图片的url地址
    :param imgFile: 文件夹位置
    :param imgName:  图片名
    :return:
    '''
    # 判断文件夹是否存在，否则创建
    if os.path.exists(imgFile):
        pass
    else:
        os.makedirs(imgFile)
    try:
        f = open(imgFile + str(imgName) + ".jpg", 'wb')
        f.write((urllib.request.urlopen(urlImg)).read())
        f.close()
    except Exception as e:
        print(str(imgName) + " 出现下载出错=================================================error,再次重试")
        downImg(imgFile, urlImg, imgName)

def getHtml(url):
    '''
    获取网页
    :param url: 网页地址
    :return: 返回网页源码
    '''
    try:
        # # 带上参数，让他更像浏览器
        headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'}
        # 超时设置
        timeout = 10
        socket.setdefaulttimeout(timeout)
        req = urllib.request.Request(url=url, headers=headers)

        html = urllib.request.urlopen(req).read().decode('utf-8')
        # print("网页源码：" + html)
        return html
    except (Exception, TimeoutError) as e:
        print("没有返回数据，等待10秒后继续请求")
        # time.sleep(3)
        getHtml(url)


def getBaseUrl(html):
    '''
    获取基页的分页面
    :param html: 主页面的url
    :return: 全部分页面的地址
    '''
    p = r"<a class='l_s' href=\'([^']+)"
    urlList = re.findall(p, str(html))
    return urlList

def getImg(html):
    # p = r'onerror="cerrmsg()" onload="initImg();movePage(this);prvLoadNext()" src=\"([^"]+)'
    '''
    获取图片的name
    :param html:
    :return:
    '''
    p = r'img id="img\d\d\d\d" name=\"([^"]+)'
    imgList = re.findall(p, str(html))
    return imgList


def decryptionImg(name):
    '''
    界面图片的地址
    :param name: 是图片的ID的name 列表值
    :return: 返回图片的地址
    '''
    # print("要解析的图片：" + str(name[0]))
    # 调用js
    f = open("decryptionImg.js", 'r', encoding='UTF-8')
    line = f.readline()
    html = ''
    while line:
        html = html + line
        line = f.readline()

    # 编译并加载js文件内容
    cxt = execjs.compile(html)

    # 调用JS执行，其中 unsuan 是函数名，name是参数
    textCxt = cxt.call('unsuan', name[0])
    print("解析出的图片地址：" + baseImg + textCxt)
    return baseImg + textCxt


def getEndPage(html):
    '''
    获取最后的结尾页
    :param html:
    :return:
    '''
    p = r'input name="hdPageCount" type="hidden" id="hdPageCount" value=\"([^"]+)'
    endPage = re.findall(p, str(html))
    return endPage[0]

def getPresentPage(html):
    '''
    获取当前的页码
    :param html:
    :return:
    '''
    p = r'<input name="hdPageIndex" type="hidden" id="hdPageIndex" value=\"([^"]+)'
    page = re.findall(p, str(html))
    return page[0]

def nextUrl(html, nextPage):
    '''
    下一页的地址拼接
    :param nextPage: 下一页的页码
    :param html: 页面
    :return: 下一页的地址
    '''
    p = r'<input name="hdVolID" type="hidden" id="hdVolID" value=\"([^"]+)'
    nextInt = re.findall(p, str(html))
    url = 'http://www.hhcool.com/cool' + str(nextInt[0]) + '/' + str(nextPage) + '.html?s=1'
    return url

def isStrHTML(mUrl):
    '''
    检测是否字符串，如果是的话，就放行，否则要继续去获取HTML，说明HTML错误
    :param sonHtml: 请求地址
    :return:
    '''
    sonHtml = getHtml(mUrl)
    if type(sonHtml) != str:
        print("不是字符串,开始重新获取···")
        isStrHTML(mUrl)
    else:
        # print("是字符串")
        return sonHtml








mainDef()

